/*
 * @(#)RuleManager.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.rules.core;

import java.io.File;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mandarax.eca.ActionException;
import org.mandarax.kernel.Clause;
import org.mandarax.kernel.ClauseSet;
import org.mandarax.kernel.ConstantTerm;
import org.mandarax.kernel.Fact;
import org.mandarax.kernel.Function;
import org.mandarax.kernel.InferenceEngine;
import org.mandarax.kernel.InferenceException;
import org.mandarax.kernel.KnowledgeBase;
import org.mandarax.kernel.Predicate;
import org.mandarax.kernel.Query;
import org.mandarax.kernel.ResultSet;
import org.mandarax.kernel.Rule;
import org.mandarax.kernel.SimplePredicate;
import org.mandarax.kernel.Term;
import org.mandarax.kernel.meta.JFunction;
import org.mandarax.lib.text.StringArithmetic;
import org.mandarax.reference.AdvancedKnowledgeBase;
import org.mandarax.reference.DerivationNodeImpl;
import org.mandarax.reference.ResolutionInferenceEngine4;
import org.mandarax.util.LogicFactorySupport;
import org.mandarax.util.TermIterator;

import com.dcivision.dms.bean.EmailMessageToRule;
import com.dcivision.dms.web.MaintEmailArchiveRuleForm;
import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.GlobalConstant;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.SystemParameterConstant;
import com.dcivision.framework.SystemParameterFactory;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.framework.bean.BeansSorter;
import com.dcivision.rules.RuleOperationConstant;
import com.dcivision.rules.action.RuleAction;
import com.dcivision.rules.action.RuleActionSetAction;
import com.dcivision.rules.bean.RuleBaseObject;
import com.dcivision.rules.bean.RuleConclusion;
import com.dcivision.rules.bean.RuleCondition;
import com.dcivision.rules.dao.RuleBaseObjectDAObject;

/**
 * <p>Class Name:  RuleManager </p>
 * <p>Description: This class offer some function to handle the rule.</p>
 * 
 * @author         Tony Chen
 * @company        DCIVision Limited
 * @creation date  25/07/2005
 * @version        $Revision: 1.26 $
 */
public class RuleManager {

	public static final String REPLACESTR = "CCCCCC";
  protected Log log = LogFactory.getLog(this.getClass().getName());
	private SessionContainer sessionContainer = null;
	private Connection dbConn = null;

	public RuleManager(SessionContainer sessionContainer, Connection dbConn){
	 	this.sessionContainer = sessionContainer;
	 	this.dbConn = dbConn;
	}
	/**
	 * Utility method to create a JFunction.
	 * @param name a function name.
	 * @param clazz the declaring class
	 * @return a JFunction
	 */
	public JFunction createFunction(String name,Class clazz) throws ApplicationException {
		Class[] param = {};
		return createFunction(name,clazz,param);
	}
	
	/**
	 * Utility method to create a JFunction.
	 * @param name a function name.
	 * @param clazz the declaring class
	 * @param clazz1 a parameter class
	 * @return a JFunction
	 */
	public JFunction createFunction(String name,Class clazz,Class clazz1) throws ApplicationException {
		Class[] param = {clazz1};
		return createFunction(name,clazz,param);
	}
	
	/**
	 * Utility method to create a JFunction.
	 * @param name a function name.
	 * @param clazz the declaring class
	 * @param clazzes parameter classes
	 * @return a JFunction
	 */
	public JFunction createFunction(String name,Class clazz,Class[] clazzes) throws ApplicationException {
		Method method = null;
		try {
			method = clazz.getMethod(name,clazzes);
		} catch (SecurityException e) {
			log.debug("Indicate a security violation.");
			throw new ApplicationException("Indicate a security violation", e);
		} catch (NoSuchMethodException e) {
			log.debug("No such method.");
			throw new ApplicationException("No such method.", e);
		}
		JFunction jFunction = new JFunction(method);			
		return jFunction;
	}

	/**
	 * perform the email archive rule, when receive a email message, 
	 * to query the public KB and the private KB, to get these rules be up to the mustard.
	 * and perform the rule action
	 * @param emailMessage a email message bean
	 * @throws ApplicationException
	 */
	public void performEmailArchiveRule(EmailMessageToRule emailMessage ) throws ApplicationException {			
    log.debug("Perform Email ArchiveRule Begin. ");
    log.debug("getMessgeContentString:" + emailMessage.getMessgeContentString());
    log.debug("getCCEmailAddressAndUserIDGroupIDRoleID:" + emailMessage.getCCEmailAddressAndUserIDGroupIDRoleID());
    log.debug("getToEmailAddressAndUserIDGroupIDRoleID:" + emailMessage.getToEmailAddressAndUserIDGroupIDRoleID());
    log.debug("getSenderEmailAddressAndUserIDGroupIDRoleID:" + emailMessage.getSenderEmailAddressAndUserIDGroupIDRoleID());
    log.debug("getSubject:" + emailMessage.getSubject());
    
	  //get the public KB file name .
	  String publicKBName = RuleOperationConstant.KB_PREFIX_DMS + "_" +
													RuleOperationConstant.RULE_CATEGORY_EMAIL_ARCHIVE + "_" + 
		                      RuleOperationConstant.RULE_TYPE_PUBLIC + ".zip";	
	  
	  String privateKBName = "";
	  if ( !Utility.isEmpty(emailMessage.getMessgeUserID()) ){
	    //get the user private rule KB file name.
	    privateKBName = RuleOperationConstant.KB_PREFIX_DMS + "_" +
		                       RuleOperationConstant.RULE_CATEGORY_EMAIL_ARCHIVE + "_" + 
													 RuleOperationConstant.RULE_TYPE_PRIVATE + "_" +
													 emailMessage.getMessgeUserID() + ".zip";
	  }
	  
	  //get the public KB file & private file.
    File publicKBFile = null;
    File privateKBFile = null;
    if(!emailMessage.getIsPrivaeteRule()){
      publicKBFile = new File(getKBFilePath() + "/" + publicKBName);
    }else{
      privateKBFile = new File(getKBFilePath() + "/" + privateKBName);
    }
	  
	 // log.debug("Public KB File : " + publicKBFile.getAbsolutePath());
//	  log.debug("Private KB File : " + privateKBFile.getAbsolutePath());
	  
	  RuleBaseObjectDAObject ruleObjDAO = new RuleBaseObjectDAObject(this.sessionContainer, this.dbConn);
	  
	  //get the public KB or private KB	  
	  KnowledgeBase kb = null;
    String kbFileName="";
	  if (emailMessage.getIsPrivaeteRule()) {	  
	  	if (privateKBFile!=null && privateKBFile.exists() ) {	
	  	  kb = ruleObjDAO.importKnowledgeBase(privateKBFile);
        kbFileName=privateKBName;
	  	  log.debug("Import Private KB finish!");
	  	}
	  } else {
	  	if (publicKBFile!=null && publicKBFile.exists() ) {
	  	  kb = ruleObjDAO.importKnowledgeBase(publicKBFile);
        kbFileName=publicKBName;
	  	  log.debug("Import Public KB finish!");
	  	}
	  }
	  	  
	  log.debug("sender: " + emailMessage.getSender());
	  if (!Utility.isEmpty(kb)) {  
	  	kb.add(getSystemSenderRule());	  	
	  	this.performRule(kb, kbFileName, emailMessage, emailMessage.getClass());        
	  }
	  log.debug("Perform Email ArchiveRule End. ");
	}
	
	/**
	 * perform rule 
	 * @param kb  a KnowledgeBase 
	 * @param kbFileName 
	 * @param object  a AbstractBaseObject object
	 * @param classObj a class Object
	 * @throws ApplicationException
	 */
	public void performRule(KnowledgeBase kb, String kbFileName, Object object, Class classObj ) throws ApplicationException {
    log.debug("Perform Rule Start........");
	  ResolutionInferenceEngine4 ie = new ResolutionInferenceEngine4 ();	
	  Predicate predicate = new SimplePredicate(RuleOperationConstant.SIMPLE_PREDICATE_NAME, new Class[]{RuleActionSetAction.class, classObj});
    EmailMessageToRule emailMessageToRule = (EmailMessageToRule) object;
    String ruleCreatorIDStr = "";
    
	  //filter enable rule
	  kb = this.filterEnableRule(kb);
	  
	  Query query = getQuery(predicate, object);
	  try {
	  	//get the rule be up to the mustard 
	  	ResultSet result = ie.query(query,kb,InferenceEngine.ALL,InferenceEngine.BUBBLE_EXCEPTIONS);	  	  
	  	
      log.debug("########################### before filter apply other result rule ########################");
      for(int i = 0; i < kb.getClauseSets().size(); i++){
        log.debug( ((Rule)(kb.getClauseSets().get(i))).getBody()  );
        log.debug( ( (Rule)(kb.getClauseSets().get(i))).getContainer() );  
      }
      log.debug("########################### before filter apply other result rule ########################");
            
	  	//filter apply other in the result	  	
	  	KnowledgeBase resultKB = this.filterApplyOther(kb, result);	  	
	  	
	  	log.debug("########################### after filter apply other result rule ########################");
      
      Map ruleNameCreatorMap = getRuleNameCreatorMap(resultKB);

      
	  	ResultSet filterResult = ie.query(query,resultKB,InferenceEngine.ALL,InferenceEngine.BUBBLE_EXCEPTIONS);	 
	  	log.debug("get the result. first ");
	  	
	  	//record the executed action.
	  	//Map ruleActionMap = new HashMap();
      List ruleNameActionTargetList = new ArrayList();
	  	while(filterResult.next()){	  
	  		log.debug("get the result.");
        
        
	  		//perform the action
	  		RuleActionSetAction actionSet = (RuleActionSetAction)filterResult.getResult(RuleActionSetAction.class, "action");
	  		
	  		List actionList = actionSet.getActions();

       
	  		for (int i = 0; i < actionList.size(); i++){
	  			log.debug("Rule Action is " + actionList.get(i));
	  			RuleAction tmpAction = (RuleAction)actionList.get(i);
	  			
	  			log.debug("Current Action is " + tmpAction);
	  			log.debug("Current Action Name is :" + tmpAction.getClass().getName());
	  			log.debug("The action target is " + tmpAction.getTarget());
          
           String nameActionTarget = tmpAction.getRuleName()+tmpAction.getClass().getName()+tmpAction.getTarget().toString();
	  			
           if (!ruleNameActionTargetList.contains(nameActionTarget)) {
             
            log.debug("Execute the action." + tmpAction.getClass().getName());

            emailMessageToRule.setRuleCreatorIDStr((String)ruleNameCreatorMap.get(tmpAction.getRuleName()));
            Object[] objects = new Object[3];
            //EmailMessageToRule emailMessageToRule = (EmailMessageToRule) object;
            objects[0] = object;
            objects[1] = kbFileName;
            objects[2] = emailMessageToRule.getIsPrivaeteRule() ? "Private" : "Public"; // getRuleInfo(filterResult,object);

            tmpAction.perform(objects);

            ruleNameActionTargetList.add(nameActionTarget);
            
            log.debug("perform the ation success!");
          }	 
	  		}  				  			
	  	}	
	  	
	  } catch (InferenceException e) {
	  	log.debug("Inference Exception.");
	  	throw new ApplicationException("Inference Error.", e);
	  } catch (ActionException e1) {
	  	log.debug("Action Exception.");
	  	throw new ApplicationException("Action Error.", e1);
	  }
	}
  /**
   * @param resultKB
   * @return
   */
  private Map getRuleNameCreatorMap(KnowledgeBase resultKB) {
    Map ruleNameCreatorMap = new HashMap();
    String ruleName="",ruleCreator="";
    for(int i = 0; i < resultKB.getClauseSets().size(); i++){
      log.debug( ((Rule)(resultKB.getClauseSets().get(i))).getProperty(RuleOperationConstant.RULE_CREATOR_ID));
    	log.debug( ( (Rule)(resultKB.getClauseSets().get(i))).getContainer() );  
      
      if(!"0".equals(((Rule)(resultKB.getClauseSets().get(i))).getProperty(RuleOperationConstant.RULE_CREATOR_ID))){
        ruleName=((Rule)(resultKB.getClauseSets().get(i))).getProperty(RuleOperationConstant.RULE_NAME);
        ruleCreator=((Rule)(resultKB.getClauseSets().get(i))).getProperty(RuleOperationConstant.RULE_CREATOR_ID);
        ruleNameCreatorMap.put(ruleName, ruleCreator);
      }
    }
    return ruleNameCreatorMap;
  }
  /**
   * @deprecated
   * @param ruleActionMap
   * @param ruleNameList 
   * @param tmpAction
   * @return
   */
  private boolean canExecuteAction(Map ruleActionMap, List ruleNameList, RuleAction tmpAction) {
    String key = tmpAction.getRuleName()+tmpAction.getClass().getName()+tmpAction.getTarget().toString();
    boolean isSameAction =!Utility.isEmpty(ruleActionMap.get(key)) 
            &&tmpAction.getTarget().equals(ruleActionMap.get(key));
    boolean isSameRule = ruleNameList.contains(tmpAction.getRuleName()) ;  
    return !isSameRule||!isSameAction;
  }
  /**
   * @param object
   * @param ie
   * @param query
   * @param filterResult
   * @throws InferenceException
   */
  private Object[] getMatchedRuleInfo(Object object, ResultSet filterResult) throws InferenceException {
    Object[] objects = new Object[2];
    objects[0]=object;
    objects[1]=getRuleInfo(filterResult,object);
    return objects;
  }
	/**
   * 
   * @param filterResult a result
	 * @param object 
   * @return ruleinfo
	 * @throws InferenceException 
	 */
	private Object getRuleInfo(ResultSet filterResult, Object object) throws InferenceException {
    Map ruleInfo = new HashMap();
    EmailMessageToRule emailMessageToRule = (EmailMessageToRule)object;
    RuleMemberFactory factory = new RuleMemberFactory();
    StringBuffer ruleName = new StringBuffer();
    StringBuffer ruleDesc = new StringBuffer();
    StringBuffer action = new StringBuffer();
    StringBuffer conditionName = new StringBuffer();
    StringBuffer conditionValue = new StringBuffer();
    StringBuffer conditionPredicate = new StringBuffer();
    List ruleNameList = new ArrayList();
      DerivationNodeImpl node = (DerivationNodeImpl) (filterResult.getProof().getRoot());

      for (java.util.Iterator iter = node.getSubNodes().iterator(); iter.hasNext();) {
        DerivationNodeImpl nextNode = (DerivationNodeImpl) iter.next();
        if (nextNode.getState() == DerivationNodeImpl.FAILED) {
          continue;
        }
        Rule rule = (Rule) (nextNode.getAppliedClause());
        if (ruleNameList.contains(rule.getProperty(RuleOperationConstant.RULE_ID))) {
          continue;
        }
        ruleNameList.add(rule.getProperty(RuleOperationConstant.RULE_ID));
        ruleName.append(rule.getProperty(RuleOperationConstant.RULE_NAME) + " , ");
        ruleDesc.append("["+rule.getProperty(RuleOperationConstant.RULE_NAME)+"] :"
                        +rule.getProperty(RuleOperationConstant.RULE_DESCRIPTION) + " <br> ");

        String[] conditions = getCondition(factory, rule);
        conditionName.append(conditions[0] + " , ");
        conditionPredicate.append(conditions[1] + " , ");
        conditionValue.append(conditions[2] + " , ");
        action.append(getAction(factory, rule) + " , ");
      }
    ruleInfo.put("ruleType", emailMessageToRule.getIsPrivaeteRule()?"Private":"Public");
    ruleInfo.put("ruleName", cutEndComma(ruleName.toString()));
    ruleInfo.put("ruleDesc", cutEndComma(ruleDesc.toString()));
    ruleInfo.put("action", cutEndComma(action.toString()));
    ruleInfo.put("conditionName", cutEndComma(conditionName.toString()));
    ruleInfo.put("conditionPredicate", cutEndComma(conditionPredicate.toString()));
    ruleInfo.put("conditionValue", cutEndComma(conditionValue.toString()));
    

    return ruleInfo;
  }
  private String cutEndComma(String str) {
    if (Utility.isEmpty(str)) {
      return "";
    }
    if (!str.trim().endsWith(",")) {
      return str;
    }
    str = str.substring(0, str.lastIndexOf(","));
    return str;
  }
  /**
   * @param factory
   * @param rule
   */
  private String[] getCondition(RuleMemberFactory factory, Rule rule) {
    List conditionList = factory.getCondition(rule);
    String[] conditions = new String[3];
    StringBuffer conditionName = new StringBuffer();
    StringBuffer conditionValue = new StringBuffer();
    StringBuffer conditionPredicate = new StringBuffer();
    for (int i = 0; i < conditionList.size(); i++) {
      RuleCondition condition = (RuleCondition) conditionList.get(i);
      conditionName.append(condition.getTerm()[0]);
      if (!Utility.isEmpty(condition.getTerm()[1])) {
        conditionValue.append(replaceEspecialChar(condition.getTerm()[1]));
      }
      else {
        conditionValue.append(" ");
      }
      if (!Utility.isEmpty(condition.getPredicateName())) {
        conditionPredicate.append(condition.getPredicateName());
      }
      else {
        conditionPredicate.append(" ");
      }
      if (i < conditionList.size() - 1) {
        conditionName.append(" , ");
        conditionValue.append(" , ");
        conditionPredicate.append(" , ");
      }
    }
    conditions[0]=conditionName.toString();
    conditions[1]=conditionPredicate.toString();
    conditions[2]=conditionValue.toString();
    return conditions;
  }
  private String replaceEspecialChar(String inputStr) {
    String outStr="";
    if(!Utility.isEmpty(inputStr)){
      outStr = inputStr;
      if(inputStr.indexOf(",")!=-1){
        outStr=inputStr.replaceAll(",", REPLACESTR);
      }
    }
    return outStr;
  }
  /**
   * @param factory
   * @param rule
   */
  private String getAction(RuleMemberFactory factory, Rule rule) {
    List actionList =factory.getConclusion(rule);
    StringBuffer actions = new StringBuffer();
    for(int i=0;i<actionList.size();i++){
      RuleConclusion conclusion = (RuleConclusion)actionList.get(i);
      actions.append(conclusion.getActionClassName());
      if(i<actionList.size()-1){
        actions.append(" & ");        
      }
    }
    return actions.toString();
  }
  /**
   * get a Query by predicate, object.
   * 
   * @param predicate a predicate,
   * @param object a object bean
   * @return query
   */
  public Query getQuery(Predicate predicate, Object object){
  	LogicFactorySupport lfs = new LogicFactorySupport();
  	Query query = lfs.query(
				lfs.fact(
						predicate,
						"action",
						object
				),
				"get appropriate actions"
    );
  	
  	return query;
  }
		
	
	/**
	 * get the KnowledgeBase file path
	 * @return Stirng
	 */
	public String getKBFilePath(){
		String path = SystemParameterFactory.getSystemParameter(SystemParameterConstant.RULES_KB_FILE_PATH);
		return path;
	}
	

  /**
   * get a rule from derivation node
   * @param node a derivation node
   * @return Rule
   */
  private KnowledgeBase getKnowledgeBase(org.mandarax.reference.DerivationNodeImpl node) {		
  	KnowledgeBase resultKB = new AdvancedKnowledgeBase();
  	
		for (java.util.Iterator iter = node.getSubNodes().iterator();iter.hasNext();) {
			org.mandarax.reference.DerivationNodeImpl nextNode = (org.mandarax.reference.DerivationNodeImpl)iter.next();			
			Rule rule = (Rule)(nextNode.getAppliedClause());
			
			log.debug("get a rule :" + rule.getHead());
			resultKB.add(rule);
			
			if (nextNode.getState() != org.mandarax.reference.DerivationNodeImpl.FAILED) {
				getKnowledgeBase(nextNode);
			}
		} 
		
		return resultKB;
	}
  
  /**
   * filter apply other
   * @param kb  a KnowledgeBase
   * @param result  a ResultSet
   * @return KnowledgeBase
   * @throws ApplicationException
   */
  private KnowledgeBase filterApplyOther(KnowledgeBase kb, ResultSet result) throws ApplicationException{
  	KnowledgeBase resultKB = new AdvancedKnowledgeBase();
  	RuleMemberFactory factory = new RuleMemberFactory();
  	List ruleObjList = new ArrayList();
  	    
  	try {      
  		while ( result.next()) {
  			org.mandarax.reference.DerivationNodeImpl node = (org.mandarax.reference.DerivationNodeImpl)(result.getProof().getRoot() );
  			List clauseSetList = this.getKnowledgeBase(node).getClauseSets();
  			
  			//hold the rule action & rule  
  			ClauseSet oldContainer = null;
  			for(int i = 0; i < clauseSetList.size(); i++){
  				org.mandarax.kernel.ClauseSet cs = (org.mandarax.kernel.ClauseSet)clauseSetList.get(i);
  				Rule rule = (Rule)cs;  		
  				
  				log.debug(rule.getBody());
  				log.debug(rule.getContainer());  					
  				log.debug(rule.getProperties());
  				
  				if ( !rule.getContainer().equals(oldContainer) ) {
  					oldContainer = rule.getContainer();
  					Rule tmpRule = this.getRuleByClauseSet(kb, rule.getContainer());
  					if ( !Utility.isEmpty(tmpRule) ) {
  						ruleObjList.add( factory.getRuleData(tmpRule) );
  					}
  				}
  			}  	    
      }
  	} catch (InferenceException e) {
  		log.error("Inference Exception. " + e);
  		throw new ApplicationException ("Inference error. ");
  	}
  	
    
    //Sort by the rule seq no.
  	ruleObjList = BeansSorter.sortAscending(ruleObjList, RuleOperationConstant.RULE_SEQ_NO );
  	
    //check the not apply other
  	for(int i = 0; i < ruleObjList.size(); i++){
  		RuleBaseObject ruleObj = (RuleBaseObject)ruleObjList.get(i);
  		Rule rule = ruleObj.getRuleSource(); 
  		String applyOther = rule.getProperty(RuleOperationConstant.RULE_NOT_APPLY_OTHER);
  		
  		if(GlobalConstant.TRUE.equals(applyOther)){
        resultKB.add(rule);
  			break;
  		} else {
  			resultKB.add(rule);
  		}
  	}
  	return resultKB;
  }

  /**
   * filter enable rule
   * @param kb a KnowledgeBase
   * @return KnowledgeBase
   */
  private KnowledgeBase filterEnableRule (KnowledgeBase kb) {
  	KnowledgeBase resultKB = new AdvancedKnowledgeBase();
  	List clauseList = kb.getClauseSets();
  	
  	for (int i = 0; i < clauseList.size(); i++) {
  		Rule rule = (Rule)clauseList.get(i);
  		if (GlobalConstant.TRUE.equals(rule.getProperty(RuleOperationConstant.RULE_STATUS_ENABLED)) ){
  			resultKB.add(rule);
  		}
  	}
  	return resultKB;
  }
  
  /**
   * get the system sender rule
   * @return Rule
   * @throws ApplicationException
   */
  private Rule getSystemSenderRule() throws ApplicationException {
    LogicFactorySupport lfs = new LogicFactorySupport();
    
    String senderAddress = SystemParameterFactory.getSystemParameter(SystemParameterConstant.SMTP_ADMIN_ADDRESS);
    Function getSender = this.createFunction(MaintEmailArchiveRuleForm.CRITERION_EMAILFROM, EmailMessageToRule.class );
    
    List actionList = new ArrayList();  
    RuleActionSetAction actionSet = new RuleActionSetAction(actionList);
    
    Predicate actionSetPred = new SimplePredicate(RuleOperationConstant.SIMPLE_PREDICATE_NAME, new Class[]{RuleActionSetAction.class, EmailMessageToRule.class});
    
    Rule rule = lfs.rule(  
        lfs.prereq(StringArithmetic.EQUAL,lfs.cplx(getSender,  "Email Message"), senderAddress),        
        lfs.fact( actionSetPred, actionSet, "Email Message" )          
    );
    
    
    rule.setProperty( RuleOperationConstant.RULE_ID, "0");
    rule.setProperty( RuleOperationConstant.RULE_NAME, "System Sender");
    rule.setProperty( RuleOperationConstant.RULE_TYPE, RuleOperationConstant.RULE_TYPE_PUBLIC);
    rule.setProperty( RuleOperationConstant.RULE_CATEGORY, RuleOperationConstant.RULE_CATEGORY_EMAIL_ARCHIVE);
    rule.setProperty( RuleOperationConstant.RULE_DESCRIPTION, "If sender equals system sender, do nothing.");
    rule.setProperty( RuleOperationConstant.RULE_CONDITION_RELATION, RuleOperationConstant.CONDITION_AND);
    
    rule.setProperty( RuleOperationConstant.RULE_SEQ_NO, TextUtility.formatNumberWithZeroPrefix(6, new Integer("0") ) );
    rule.setProperty( RuleOperationConstant.RULE_NOT_APPLY_OTHER, GlobalConstant.FALSE );
    rule.setProperty( RuleOperationConstant.RULE_STATUS_ENABLED, GlobalConstant.TRUE );
        
    rule.setProperty( RuleOperationConstant.RULE_CREATOR_ID, "0");
    rule.setProperty( RuleOperationConstant.RULE_CREATE_DATE, Utility.getCurrentTimestamp().toString() );
    rule.setProperty( RuleOperationConstant.RULE_UPDATER_ID, "0");
    rule.setProperty( RuleOperationConstant.RULE_UPDATE_DATE, Utility.getCurrentTimestamp().toString() );
    rule.setProperty( RuleOperationConstant.RULE_UPDATE_COUNT, "0" );
    
    return rule;
  }

  /**
   * get the action & target Object, for check the query rule.
   * @param clause
   * @return Object
   */
  private Object getActionTerm (Clause clause) {
  	Fact conclusion = ((Rule)clause).getHead();
  	
  	TermIterator terms = conclusion.terms();
  	while(terms.hasMoreTerms()){
  		Term term = terms.nextTerm();
  		
  		if ( term instanceof ConstantTerm ) {
  			ConstantTerm conTerm = (ConstantTerm)term;              
  			log.debug("ConstantTerm :"+conTerm.getObject());
  			return conTerm.getObject();
  			
  		} 
  	}       
    return null;
  }
  
  /**
   * get the rule by Clause Set
   * @param kb a KnowledgeBase
   * @param clauseSet a Clause Set
   * @return Rule
   */
  private Rule getRuleByClauseSet (KnowledgeBase kb, ClauseSet clauseSet) {
    List clauseList = kb.getClauseSets();
    Rule resultRule = null;
    for (int i = 0; i < clauseList.size(); i++) {
      Rule rule = (Rule)clauseList.get(i);
      if (rule.getContainer().equals(clauseSet)) {
        resultRule = rule;
        log.debug("rule body:" + rule.getBody());
        log.debug("rule container:" + rule.getContainer());
        break;
      }      
    }
    return resultRule;
  }
}
